package cn.tedu.ykmall.user.webapi.service;

import cn.tedu.ykmall.common.ex.ServiceException;
import cn.tedu.ykmall.common.web.State;
import cn.tedu.ykmall.pojo.userClient.dto.UserInsertDTO;
import cn.tedu.ykmall.pojo.userClient.dto.UserLoginDTO;
import cn.tedu.ykmall.pojo.userClient.entity.User;
import cn.tedu.ykmall.pojo.userClient.vo.UserInfoVO;
import cn.tedu.ykmall.pojo.userClient.vo.UserPasswordVO;
import cn.tedu.ykmall.user.service.IUserService;
import cn.tedu.ykmall.user.webapi.mapper.UserMapper;
import io.jsonwebtoken.Header;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class UserServiceImpl implements IUserService {
    private BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    @Autowired
    private UserMapper  userMapper;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Override
    public void addNew(UserInsertDTO userInsertDTO) {
        //注册是判断用户名、手机号
        String phone = userInsertDTO.getPhone();
        String nickname = userInsertDTO.getNickname();

        UserInsertDTO userResult = userMapper.getUser(phone,nickname);
        //通过phone判断userResult是否存在
        //是：说明该user已存在，不能再注册新增，则抛出异常：
        if (userResult!=null) {
            throw new ServiceException(State.ERR_USER_HAVE_EXISTS, "新增用户失败，用户已存在！");
        }
        //把密码加密：
        String password = userInsertDTO.getPassword();
        String encodedPassword = passwordEncoder.encode(password);
        User user = new User();
        BeanUtils.copyProperties(userInsertDTO, user);
        LocalDateTime now = LocalDateTime.now();
        Date date = new Date();
        user.setPassword(encodedPassword);
        user.setUserMoney(0.00);
        user.setUserPoint(0);
        user.setCustomerLevel(1);
        user.setGmtCreate(now);
        user.setGmtModified(now);
        user.setRegisterTime(date);
        int rows = userMapper.insert(user);
        if (rows!=1){
            throw new ServiceException(State.ERR_INSERT,
                    "添加类别失败，服务器忙（"+State.ERR_INSERT.getValue()+"），请稍后再次尝试！");
        }
    }

    private String secretKey = "asdasdasdasdasd";
    @Override
    public String login(UserLoginDTO userLoginDTO) {
        // 准备被认证数据
        Authentication authentication
                = new UsernamePasswordAuthenticationToken(
                userLoginDTO.getNickname(),
                userLoginDTO.getPassword());
        // 调用AuthenticationManager验证用户名与密码
        // 执行认证，如果此过程没有抛出异常，则表示认证通过，如果认证信息有误，将抛出异常
        Authentication authenticate = authenticationManager.authenticate(authentication);
        // 如果程序可以执行到此处，则表示登录成功
        // 生成此用户数据的JWT
        org.springframework.security.core.userdetails.User user=
                (org.springframework.security.core.userdetails.User) authenticate.getPrincipal();
        System.out.println("从认证结果中获取Principal=" + user.getClass().getName());
        Map<String, Object> claims = new HashMap<>();
        claims.put("nickname", user.getUsername());
        System.out.println("即将向JWT中写入数据=" + claims);
        String jwt = Jwts.builder()
                // Header：指定算法与当前数据类型
                // 格式为： { "alg": 算法, "typ": "jwt" }
                .setHeaderParam(Header.CONTENT_TYPE, "HS256")
                .setHeaderParam(Header.TYPE, Header.JWT_TYPE)
                // Payload：通常包含Claims（自定义数据）和过期时间
                .setClaims(claims)
                .setExpiration(new Date(System.currentTimeMillis() + 5 * 60 * 1000))
                // .Signature：由算法和密钥（secret key）这2部分组成
                // .sigSignature 由算法和密钥（secret key）这2部分组成
                .signWith(SignatureAlgorithm.HS256, secretKey)
                // 打包生成
                .compact();
        return jwt;
    }

    @Override
    public UserInfoVO getUserInfoByNickname(String nickname) {
        UserInfoVO userInfo = userMapper.getUserInfoByNickname(nickname);
        return userInfo;
    }

    @Override
    public void update(UserInfoVO userInfoVO) {
        String nickname = userInfoVO.getNickname();
        UserInfoVO result = userMapper.getUserInfoByNickname(nickname);
        if (userInfoVO.getUsername().equals(result.getNickname())){
            throw new ServiceException(State.ERR_USER_HAVE_EXISTS,"修改失败，该用户名已被使用");
        }
        userMapper.updateUserInfoByNickname(nickname,userInfoVO);
    }

    @Override
    public void updatePassword(UserPasswordVO userPasswordVO) {
        String password = userPasswordVO.getPassword();
//        UserInfoVO result = userMapper.getUserInfoByNickname(password);
////        if (result==null){
////            throw new ServiceException(State.ERR_USER_NOT_FOUND,"修改密码失败，原密码不存在！");
////        }
        if (userPasswordVO.getPassword().equals(userPasswordVO.getNewPassword())){
            throw new ServiceException(State.ERR_USER_PASSWORD_REPEAT,"修改密码失败，新密码和原密码不可一样！");
        }
        if (!userPasswordVO.getNewPassword().equals(userPasswordVO.getRePassword())){
            throw new ServiceException(State.ERR_USER_PASSWORD_ERROR, "修改密码失败，复写密码和新密码不一致！");
        }
        String encodedPassword = passwordEncoder.encode(userPasswordVO.getNewPassword());
        userMapper.updatePassword(password, encodedPassword);
    }
}
